home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / GLOBAL.C < prev    next >
C/C++ Source or Header  |  1989-12-31  |  10KB  |  549 lines

  1. #include <signal.h>
  2. #include <errno.h>
  3. #include <pwd.h>
  4. #include "config.h"
  5.  
  6. export char *home_directory;
  7. export char *nn_directory;
  8. export char news_directory[] = NEWS_DIRECTORY;    /* /usr/spool/news */
  9. export char lib_directory[]  = LIB_DIRECTORY;    /* /usr/local/lib/nn     */
  10. export char db_directory[]   = DB_DIRECTORY;    /* /usr/spool/nn    */
  11. export char *log_entry_filter = NULL;
  12.  
  13. export char *temp_file;
  14.  
  15. export char *pager = PAGER;        /* pg or more        */
  16.  
  17. export int is_master;
  18.  
  19. #ifdef HAVE_MULTIGROUP
  20. #ifndef NGROUPS
  21. #include <sys/param.h>
  22. #endif
  23. #ifndef GIDSET_TYPE
  24. #define GIDSET_TYPE int
  25. #endif
  26. static int ngroups;
  27. static GIDSET_TYPE gidset[NGROUPS];
  28.  
  29. static in_grplist(gid)
  30. GIDSET_TYPE gid;
  31. {
  32.     int n;
  33.   
  34.     for (n = 0; n < ngroups; ++n)
  35.     if (gidset[n] == gid) return 1;
  36.  
  37.     return 0;
  38. }
  39.  
  40. #define group_access(gpid)    in_grplist((GIDSET_TYPE)(gpid))
  41. #else
  42. #define group_access(gid)    ((gid) == group_id)
  43. #endif
  44.    
  45. /* signal handler interface */
  46.  
  47. export int s_hangup        = 0;    /* hangup signal */
  48. export int s_keyboard        = 0;    /* keyboard interrupt */
  49. export int s_pipe        = 0;    /* broken pipe */
  50. export int s_redraw        = 0;    /* redraw signal (if job control) */
  51.  
  52. static sig_type catch_hangup(n)
  53. {
  54.     signal(n, SIG_IGN);
  55.     
  56.     s_hangup++;
  57. }
  58.  
  59. static sig_type catch_keyboard(n)
  60. {
  61.     s_keyboard++;
  62.     
  63. #ifdef RESET_SIGNAL_WHEN_CAUGHT
  64.     signal(n, catch_keyboard);
  65. #endif    
  66. }
  67.  
  68. static sig_type catch_pipe(n)
  69. {
  70.     s_pipe++;
  71.     
  72. #ifdef RESET_SIGNAL_WHEN_CAUGHT
  73.     signal(n, catch_pipe);
  74. #endif    
  75. }
  76.  
  77. #ifdef HAVE_JOBCONTROL
  78. static sig_type catch_suspend(n)
  79. {
  80.     s_redraw++;
  81.  
  82. #ifdef RESET_SIGNAL_WHEN_CAUGHT
  83.     signal(n, catch_redraw);
  84. #endif
  85.  
  86.     suspend_nn();
  87. }
  88. #endif
  89.  
  90. /*
  91.  * who:
  92.  *    0    nn
  93.  *    1    nnmaster
  94.  *    2    nnadmin
  95.  *    3    nncheck
  96.  */
  97.  
  98. init_global(who)
  99. int who;
  100. {
  101.     char *env;
  102.     unsigned short getuid(), getgid();
  103.     int getpid();
  104.     int suspend_nn();
  105.  
  106.     is_master = (who == 1);
  107.     
  108.     signal(SIGTERM, catch_hangup);
  109.     signal(SIGHUP,  catch_hangup);
  110.     signal(SIGPIPE, catch_pipe);
  111.     signal(SIGALRM, SIG_IGN);
  112.     
  113. #ifdef SIGPWR
  114.     signal(SIGPWR, catch_hangup);
  115. #endif
  116.  
  117.     user_id = getuid();
  118.  
  119. #ifdef HAVE_MULTIGROUP
  120.     ngroups = getgroups(NGROUPS, gidset);    /* Get users's group set */
  121.     group_id = gidset[0];    /* not used, but just in case... */
  122. #else
  123.     group_id = getgid();
  124. #endif
  125.  
  126.     process_id = getpid();
  127.     
  128.     if (is_master) {
  129.     signal(SIGINT,  catch_hangup);
  130.     signal(SIGQUIT, catch_hangup);
  131.     return 0;
  132.     }
  133.     
  134.     signal(SIGINT,  catch_keyboard);
  135.     signal(SIGQUIT, catch_keyboard);
  136. #ifdef HAVE_JOBCONTROL
  137.     signal(SIGTSTP, catch_suspend);
  138. #endif    
  139.  
  140.     if ((home_directory = getenv("HOME")) == NULL) 
  141.     user_error("No HOME environment variable");
  142.  
  143.     nn_directory = mk_file_name(home_directory, ".nn");
  144.     
  145.     if (who != 2 && !file_exist(nn_directory, "drwx")) {
  146.     if (who == 3) return -1;
  147.     mkdir(nn_directory, 0755);    /* should check here */
  148.     }
  149.     
  150.     return 0;
  151. }
  152.  
  153. new_temp_file()
  154. {
  155.     static char buf[FILENAME];
  156.     static char *temp_dir = NULL;
  157.     
  158.     if (temp_dir == NULL && (temp_dir = getenv("TMPDIR")) == NULL) 
  159.     temp_dir = TMP_DIRECTORY;
  160.  
  161.     sprintf(buf, "%s/nn.XXXXXX", temp_dir);
  162.     mktemp(buf);
  163.     temp_file = buf;
  164. }
  165.  
  166. /*
  167.  * this is for admin K & W commands and for master -w
  168.  */
  169.  
  170. kill_master(sig)
  171. int sig;
  172. {
  173.     FILE *m_pid;
  174.     int  pid, ok;
  175.     char buf[10];
  176.     
  177.     m_pid = open_file(relative(lib_directory, "MPID"), OPEN_READ);
  178.     if (m_pid == NULL) {
  179.     errno = ESRCH;
  180.     return 0;
  181.     }
  182.     
  183.     ok = 0;    /* not yet */
  184.  
  185.     if (fgets(buf, 10, m_pid) == NULL)
  186.     printf("MPID file is empty\n");
  187.     else {
  188.     pid = atoi(buf);
  189.     if (pid <= 2)
  190.         printf("MPID file contains illegal process id: %d\n", pid);
  191.     else
  192.         if (kill(pid, sig) != -1) ok++;
  193.     }
  194.  
  195.     fclose(m_pid);
  196.  
  197.     return ok;
  198. }    
  199.  
  200.     
  201. mem_check(addr, size, msg)
  202. char *addr, *msg;
  203. int size;
  204. {
  205.     if (addr == NULL) {
  206.     if (is_master)
  207.         sys_error("Cannot allocate %d %s", size, msg);
  208.     else    
  209.         user_error("Cannot allocate %d %s", size, msg);
  210.     }
  211. }
  212.  
  213. FILE *open_file(name, mode)
  214. char *name;
  215. int mode;
  216. {
  217.     FILE *f;
  218.     int fd;
  219.     
  220.     if ((mode & DONT_CREATE) && !file_exist(name, (char *)NULL))
  221.     return NULL;
  222.  
  223.     switch (mode & 0x0f) {
  224.  
  225.      case OPEN_READ:
  226.     
  227.     f = fopen(name, "r");
  228.     break;
  229.     
  230.      case OPEN_UPDATE:
  231.     
  232. /*    f = fopen(name, "r+");     -- not reliable on many systems (sigh) */
  233.  
  234.     if ((fd = open(name, O_WRONLY)) >= 0) {
  235.         if ((f = fdopen(fd, "w")) != NULL) return f;
  236.         close(fd);
  237.     }
  238.  
  239.     /* fall thru */
  240.     
  241.      case OPEN_CREATE:
  242.     
  243.     f = fopen(name, "w");
  244.     break;
  245.     
  246.      case OPEN_APPEND:
  247.     
  248.     f = fopen(name, "a");
  249.     break;
  250.  
  251.      default:
  252.     
  253.     sys_error("Illegal mode: open_file(%s, %d)", name, mode);
  254.     }
  255.  
  256.     if (f) {
  257.     if (mode & OPEN_UNLINK) unlink(name);
  258.     return f;
  259.     }
  260.     
  261.     if ((mode & MUST_EXIST) == 0) return NULL;
  262.     
  263.     if (is_master)
  264.     sys_error("Cannot open file %s, mode: %d", name, mode);
  265.     else {
  266.     log_entry('R', "Client cannot open file %s, mode: %d", name, mode);
  267.     user_error("Cannot open file %s", name);
  268.     }
  269.     
  270.     return NULL;
  271. }
  272.  
  273.  
  274.  
  275.  
  276. /*
  277.  *     relative -- concat directory name and file name
  278.  */
  279.  
  280. char *relative(dir, name)
  281. char *dir, *name;
  282. {
  283.     static char concat_path[FILENAME];
  284.  
  285.     sprintf(concat_path, "%s/%s", dir, name);
  286.     return concat_path;
  287. }
  288.  
  289.  
  290. char *mk_file_name(dir, name)
  291. char *dir, *name;
  292. {
  293.     char *buf;
  294.     
  295.     buf = malloc((unsigned)(strlen(dir) + strlen(name) + 2));
  296.     mem_check(buf, 1, "file name");
  297.     sprintf(buf, "%s/%s", dir, name);
  298.  
  299.     return buf;
  300. }
  301.  
  302.  
  303. char *home_relative(dir)
  304. char *dir;
  305. {
  306.     if (dir) {
  307.     if (*dir == '/') 
  308.         return copy_str(dir);
  309.     else {
  310.         if (*dir == '~' && *++dir == '/') dir++;
  311.         return mk_file_name(home_directory, dir);
  312.     }
  313.     }
  314.     return NULL;
  315. }
  316.  
  317.     
  318. char *copy_str(str)
  319. char *str;
  320. {
  321.     char *new;
  322.     
  323.     new = malloc((unsigned)(strlen(str) + 1));
  324.     mem_check(new, 1, "string");
  325.     if (new) strcpy(new, str);
  326.  
  327.     return new;
  328. }
  329.  
  330. time_t m_time(f)
  331. FILE *f;
  332. {
  333.     struct stat st;
  334.     
  335.     if (fstat(fileno(f), &st) < 0) return 0;
  336.     return st.st_mtime;
  337. }
  338.  
  339.  
  340. time_t file_exist(name, mode)
  341. char *name;
  342. char *mode;
  343. {
  344.     struct stat statb;
  345.     extern int errno;
  346.     
  347.     if (stat(name, &statb)) return 0;
  348.  
  349.     if (mode == NULL) return statb.st_mtime;
  350.     
  351.     while (*mode) {
  352.     switch (*mode++) {
  353.     case 'd':
  354.         if ((statb.st_mode & S_IFMT) == S_IFDIR) continue;
  355.         errno = ENOTDIR;
  356.         return 0;
  357.     case 'f':
  358.         if ((statb.st_mode & S_IFMT) == S_IFREG) continue;
  359.         if ((statb.st_mode & S_IFMT) == 0000000) continue;
  360.         if ((statb.st_mode & S_IFMT) == S_IFDIR) {
  361.         errno = EISDIR;
  362.         return 0;
  363.         }
  364.         break;
  365.     case 'r':
  366.         if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
  367.         if ((statb.st_mode & 0040) && group_access(statb.st_gid)) continue;
  368.             if ((statb.st_mode & 0004)) continue;
  369.         break;
  370.     case 'w':
  371.         if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
  372.         if ((statb.st_mode & 0020) && group_access(statb.st_gid)) continue;
  373.             if ((statb.st_mode & 0002)) continue;
  374.         break;
  375.     case 'x':
  376.         if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
  377.         if ((statb.st_mode & 0010) && group_access(statb.st_gid)) continue;
  378.             if ((statb.st_mode & 0001)) continue;
  379.         break;
  380.     }        
  381.     errno = EACCES;
  382.     return 0;
  383.     }
  384.  
  385.     /* all modes are ok */
  386.     return statb.st_mtime;
  387. }
  388.  
  389.  
  390.  
  391. print_version(fmt)
  392. char *fmt;
  393. {
  394.     extern int Update_Level, Patch_Level;
  395.     int param;
  396.     
  397.     for (; *fmt; fmt++) {
  398.  
  399.     if (*fmt == '%') {
  400.         switch (*++fmt) {
  401.          case 'R':
  402.         param = RELEASE;
  403.         break;
  404.          case 'V':
  405.         param = VERSION;
  406.         break;
  407.          case 'P':
  408.         param = Patch_Level;
  409.         break;
  410.          case 'U':
  411.         param = Update_Level;
  412.         break;
  413.          default:
  414.         continue;
  415.         }
  416.         printf("%d", param);
  417.         continue;
  418.     } 
  419.     putchar(*fmt);
  420.     }
  421.  
  422.     fl;
  423. }
  424.  
  425. /*VARARGS*/
  426. log_entry(va_alist)
  427. va_dcl
  428. {
  429.     int type, rval;
  430.     va_list ap;
  431.  
  432.     va_start(ap);
  433.     type = va_arg1(int);
  434.     rval = enter_log(type, va_args2toN);
  435.     va_end(ap);
  436.     return rval;
  437. }
  438.  
  439. #ifdef HAVE_SYSLOG
  440. #include <syslog.h>
  441. #endif /* HAVE_SYSLOG */
  442.  
  443. /*VARARGS*/
  444. sys_error(va_alist)
  445. va_dcl
  446. {
  447.     char buf[512];
  448.     char *fmt;
  449.     FILE *f;
  450.     va_list ap;
  451.  
  452.     va_start(ap);
  453.     enter_log('E', va_args1toN);
  454.     va_end(ap);
  455.  
  456.     if (is_master) {
  457.     va_start(ap);
  458.     fmt = va_arg1(char *);
  459.     vsprintf(buf, fmt, va_args2toN);
  460.     va_end(ap);
  461.  
  462. #ifndef HAVE_SYSLOG
  463.     f = open_file("/dev/console", OPEN_CREATE);
  464.     if (f == NULL) nn_exit(8);
  465.     fprintf(f, "\n\rNNMASTER FATAL ERROR\n\r%s\n\n\r", buf);
  466.     fclose(f);
  467. #else /* HAVE_SYSLOG */
  468.     openlog("nnmaster", LOG_CONS, LOG_DAEMON);
  469.     syslog(LOG_ALERT, "%s", buf);
  470.     closelog();
  471. #endif /* HAVE_SYSLOG */
  472.     }    
  473.     nn_exit(7);
  474. }
  475.  
  476.  
  477. static enter_log(type, va_tail)
  478. char type;
  479. va_tdcl
  480. {
  481.     FILE *log;
  482.     char *msg, buf[512], logname[512];
  483.  
  484.     if (log_entry_filter != NULL)
  485.     for (msg = log_entry_filter; *msg; msg++)
  486.         if (*msg == type) return 1;
  487.  
  488.     msg  = va_arg1(char *);
  489.     vsprintf(buf, msg, va_args2toN);
  490.  
  491.     /* cannot use relative: one of the args may be generated by it */
  492.     sprintf(logname, "%s/Log", lib_directory);
  493.  
  494.     log = open_file(logname, OPEN_APPEND);
  495.     if (log == NULL) return 0;
  496.  
  497.     fprintf(log, "%c: %s (%s): %s\n", type,
  498.         date_time((time_t)0), user_name(), buf);
  499.     
  500.     fclose(log);
  501.     return 1;
  502. }
  503.  
  504.  
  505. char *user_name()
  506. {
  507.     static char *user = NULL;
  508.     struct passwd *pw, *getpwuid();
  509.  
  510.     if (is_master) return "M";
  511.     
  512.     if (user == NULL) {
  513.     pw = getpwuid((int)user_id);
  514.     if (pw == NULL) user = "?";
  515.     user = copy_str(pw->pw_name);
  516.     }
  517.     
  518.     return user;
  519. }
  520.  
  521.  
  522. char *date_time(t)
  523. time_t t;
  524. {
  525.     char *str;
  526.     
  527.     if (t == (time_t)0) time(&t);
  528.     str = ctime(&t);
  529.     
  530.     str[16] = 0;
  531.     return str+4;
  532. }
  533.  
  534.  
  535. #ifndef HAVE_MKDIR
  536.  
  537. mkdir(path, mode)
  538. char *path;
  539. int mode;
  540. {
  541.     char command[FILENAME*2 + 20];
  542.     
  543.     sprintf(command, "{ mkdir %s && chmod %o %s ; } > /dev/null 2>&1",
  544.         path, mode, path);
  545.     return system(command);
  546. }
  547.  
  548. #endif
  549.